#!/usr/bin/env python
# Purpose: Data export for HydroPlatform
# Author:
#    Hossam Almeer <halmeer@cs.ucl.ac.uk>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with HydroPlatform for details.

__revision__ = '$Revision: 489 $'

import logging
import sys, os
import hydroplatform
import Thuban

if not hasattr(sys, 'frozen'):
    import wxversion
    wxversion.select("2.8")



# Put the lib dir into the path. The lib dir contains some extra non
# really hydroplatform specific Python modules
hydroplatformdir = os.path.join(hydroplatform.__path__[0], '..')
hptdir = os.path.join(hydroplatformdir, "lib")
if os.path.isdir(hptdir):
    sys.path.insert(0, hptdir)
    
def module_check() :
    # TODO add module check !
    # FIXME : extract this into hydroplatform.__init__
    test_modules = ['numpy', 'sqlalchemy', 'networkx', 'shapely']
    for mod in test_modules:
        try:
            __import__(mod)
        except ImportError:
            raise 'Missing module %s. Please install it in order to make the HydroPlatform run' % mod


def set_thuban_path():
    # this could be done with thubaninit \
    # but it's not available when installed on win32
    import Thuban
    thubandir = os.path.join(Thuban.__path__[0], '..')
    dir = os.path.join(thubandir, "Lib")
    if os.path.isdir(dir):
        sys.path.insert(0, dir)

def win32_specific():
    # AUTOLOAD external libraries
    if sys.platform == 'win32':
        pass
        #for lib in constants.LIBS_AUTOLOAD:
        #    sys.path.append(lib)

def load_thuban():
    try:
        import Thuban
        set_thuban_path()
    except ImportError:
        # can't find Thuban
        if sys.platform == 'win32':
            # try to add default install directory of thuban into the path
            defdir = 'c:\\Program Files\\Thuban'
            if os.path.exists(defdir):
                sys.path.insert(0, defdir)    
            import Thuban
            set_thuban_path()
        elif sys.platform == 'linux2':
            # test if Debian package is installed
            defdir = '/usr/lib/thuban'
            if os.path.exists(defdir):
                sys.path.insert(0, defdir)
            import Thuban
            set_thuban_path()
        else:
            print "No thuban support"
    
logging.info("Dependency check")
load_thuban()
win32_specific()
module_check()


import codecs
from itertools import count, chain
import logging
import numpy
import os
import sets
import datetime
import hydroplatform

from sqlalchemy import and_

from hydroplatform.model import network as nt
from hydroplatform.model import fields as fd
from hydroplatform.model import units
from hydroplatform.model import database as db

#nt.Project = Project 

def_db_session = 0   # Default sqlalchemy session = most recent session opened

def open_db_con(dbcon):
    '''
    Takes a filepath, and returns an sqlalchemy session object\ which is stored in memory
    '''

    dbs = db.get_session(dbcon)
    print 'Opening db connection ........'
    print dbs
    global def_db_session
    def_db_session = dbs
    return dbs


def get_projects(dbsession):
    '''
    Takes a db connection, and returns a list of projects in the DB,\ this is a query, which returns results from both db and flushed parts of uncommited trasactions. Autoflush occurs here, although\ this can be disabled in sqlalchemy.
    '''

    projects_list = dbsession.query(nt.Project).all()
    return projects_list


def get_parent_project(net):
    '''
    Returns project of a network
    '''
    return net.project


def get_timeframe(proj_net):
    '''
    Passing in a project or a network will return the horizon and time step\ of the project.
    '''
    if isinstance(proj_net,nt.Network):
        proj_net = proj_net.project
    times_list = [proj_net.horizon_from, proj_net.horizon_to, proj_net.time_step]
    return times_list

def get_networks(proj):
    '''
    Takes a project object, and returns a list of networks
    in the project
    '''
    return proj.networks


def get_project_nodes(proj):
    '''
    Gets a list of the nodes in a project
    '''
    return proj.nodes


def get_project_links(proj):
    '''
    Gets a list of the links in a project
    '''
    return proj.nodes
    
def get_network_nodes(net):
    '''
    Gets a list of nodes in network
    '''
    return net.nodes


def get_network_links(net):
    '''
    Gets a list of links in network
    '''
    
    return net.links


def commit(dbs):
    '''
    Does a flush() and sends changes to external DB (a transaction). You could use dbs.commit().
    '''

    dbs.commit()  # local function of sqlalchemy session object
                  # see sqlalchemy doc for 
                  # possible errors/return values

def flush(dbs):
    '''
    flushing session object sends changes to db stored in memory,\ NOT to the external DB. By default, this occurs automatically\ when a query is made. 
    '''
    
    dbs.flush() # Note that flush failure causes rollback(dbs)
    return 0

def rollback(dbs):
    '''
    Rolls back all transactions, plus other effects. See: http://docs.sqlalchemy.org/en/latest/orm/session.html#rolling-back
    '''

    dbs.rollback()
    return 0

def remove_node(net, node):
    '''
    Removes a node from a network, please be careful as you can't add a node with this api
    '''
    net.remove_node(node)

def remove_link(net, link):
    '''
    Removes a link from a network, please be careful as you can't add a link with this api
    '''
    net.remove_link(node)


def has_link(network, node0, node1):
    '''
    Checks if there is a link between two nodes in a particular network Notes that this IS NOT symmetric as links are one-way
    '''
    net.has_link(node0, node1)


def get_field_type(field):
    '''
    Returns a string with the type of the field
    '''

    if isinstance(field.attribute_type, fd.Parameter):
        return "Parameter"
    elif isinstance(field.attribute_type, fd.TimeSerie):
        return "Time_Series"
    elif isinstance(field.attribute_type, fd.NodeReferences):
        return "Node_References"
    elif isinstance(field.attribute_type, fd.LinkReferences):
        return "Link_References"
    elif isinstance(field.attribute_type, fd.SeasonalParameter):
        return "Seasonal_Parameter"
    elif isinstance(field.attribute_type, fd.Table):
        return "Table"
'''
MARK : Need to work on convenient way to get object field values.  More Importantly, need to find a way to set field values easily.  Should be able to set a NodeFlied.value item to w/e I want
'''

def main():
    try:
        dbcon= 'sqlite:///C:\Users\H\hydroplatform.db' 
        dbs = open_db_con(dbcon)
        proj_list = get_projects(dbs)
        assert type(proj_list) == list 
        net_list = get_networks(proj_list[0])
        assert type(net_list) == list


    except:
        print 'Tests Failed'


if __name__=='__main__':

	main()



